// Octopod
// Copyright (c) 2005-2010
//
// GPL
//
// This file contains functions that wrap authenticated encryption, hashing,
// and public key functionality of the underlying Botan crypto library.

#ifndef OCTOPOD_CRYPTO_H__
#define OCTOPOD_CRYPTO_H__

#include <botan/botan.h>

namespace octopod {

// A namespace within which we can define crypto constants 
// and fixed known behavior, such as encoding sizes, and
// routines that don't belong to any particular crypto class
namespace crypto {

const int kRSABits = 4096; // size of RSA keys in bits
const int kKeyLength = 16; // symmetric key lengths in bytes
const int kIVLength = 16; // IV lengths for symmetric encryption in bytes
const int kHashLength = 64; // hash output length in bytes
const int kMACLength = 64; // MAC output length in bytes
const int kAEOverhead = 16; // tag overhead for AEAD mode in bytes
const int kZlibOverhead = 50000; // a rough overestimate of the extra space required for Zlib headers

const char * const kAECipher = "Serpent/EAX(128)"; // default block cipher and AEAD mode
const char * const kHash = "Skein-512"; // default hash function
const char * const kMAC = "HMAC(Skein-512)"; // default MAC algorithm
const char * const kPublicKeyEncryptionMethod = "EME1(Skein-512)"; // method to encode for PK encryption
const char * const kPublicKeySignatureMethod = "EMSA4(Skein-512)"; // method to encode for PK signatures
const char * const kDHDomain = "modp/ietf/3072"; // default DH key exchange domain
const char * const kDH_KDF = "KDF2(Skein-512)"; // default DH key derivation algorithm

// Returns a newly generated symmetric key.
// Caller is responsible for returned object.
// Upon failure returns NULL.
Botan::SymmetricKey *symmetricKeyGen();

// Returns a newly generated asymmetric private key.
// Caller is responsible for returned object.
// Upon failure returns NULL.
Botan::Private_Key *asymmetricPrivateKeyGen();

// Returns a asymmetric public key derived from the given non-NULL private key.
// Returned object is dependent upon the given private key.
// Upon failure returns NULL.
const Botan::Public_Key *getPublicKey(const Botan::Private_Key *private_key);

// Fills the given string with num random bytes.
// Assumes num is positive.
// Returns true upon success.
bool randomGen(int num, std::string *s);

// Fills the string ciphertext with the output of a one-shot
// authenticated-encryption call using the given key and plaintext.
// Overwrites the given initVector with the IV used in encryption.
// Returns true upon success.
bool authEncrypt(const Botan::SymmetricKey &key, const std::string &plaintext, std::string *ciphertext, std::string *init_vector);

// Fills the string plaintext with the output of a one-shot
// authenticated-decryption call using the given key, plaintext, and initVector.
// Returns true if the decryption succeeds and the authentication passes.
bool authDecrypt(const Botan::SymmetricKey &key, const std::string &ciphertext, const std::string &init_vector, std::string *plaintext);

// Fills the string ciphertext with the output of a one-shot
// public key encryption call using the given public key and plaintext.
// Assumes that the public key is large enough to encrypt the plaintext.
// Returns true upon success.
bool pubkeyEncrypt(const Botan::Public_Key *public_key, const std::string &plaintext, std::string *ciphertext);

// Fills the string plaintext with the output of a one-shot
// public key decryption call using the given private key and ciphertext.
// Returns true if the decryption succeeds.
bool pubkeyDecrypt(const Botan::Private_Key *private_key, const std::string &ciphertext, std::string *plaintext);

// Hashes the data in the given string and returns the hash result
std::string hash(const std::string &data);

// Computes the MAC of the data in the given string given the key.
// Overwrites the given string tag with the MAC tag.
// Returns true upon success.
bool MAC(const Botan::SymmetricKey &key, const std::string &data, std::string *tag);

// Derives a key given a base key and a salt string.
// Overwrites the given derivedKey.
// Returns true upon success.
bool KDF(const Botan::SymmetricKey &key, const std::string &salt, Botan::SymmetricKey *derived_key);

}  // namespace crypto

}  // namespace octopod

#endif  // OCTOPOD_CRYPTO_H__
